/*
  Programa GEFE - Gestión de eventos lúdicos.
  Copyright (C) 2010  Antonio Ramírez Marti

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "fichaactividad.h"

#include <QBrush>
#include <QTextFrameFormat>
#include <dialogreport.h>

#include <QDebug>
#include <QTime>
#include <QVector>
#include <QTextLength>
#include <QDir>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QTextDocumentWriter>
#include <QProgressDialog>
#include <QPrinter>
#include <QPrintDialog>


FichaActividad::FichaActividad(QObject *parent,QString nEvento) :
    QObject(parent), evento(nEvento)
{
    setup();
}

void FichaActividad::setup()
{
    this->documento=0;
    this->cursor=0;
    this->okImage=QImage(":/iconos/iconos/emblem-cool.png").scaled(20,20,Qt::KeepAspectRatio);
    this->delayImage=QImage(":/iconos/iconos/package-broken.png").scaled(20,20,Qt::KeepAspectRatio);
    this->cancelImage=QImage(":/iconos/iconos/monsterz.png").scaled(20,20,Qt::KeepAspectRatio);

}

void FichaActividad::generaFichaActividad(QSqlRecord actividad)
{
    //Limpia el posible contenido de documento y cursor
    clean();
    preparaDocumento();
    generaCabecera(actividad);
    generaHorario(actividad);
    generaDescripcion(actividad);
    generaParticipantes(actividad);
    mostrarFicha(actividad);
}

void FichaActividad::imprimeFichaActividad(QSqlRecord actividad)
{
    //Limpia el posible contenido de documento y cursor
    clean();
    preparaDocumento();
    generaCabecera(actividad);
    generaHorario(actividad);
    generaDescripcion(actividad);
    generaParticipantes(actividad);
    imprimeFicha();
}

void FichaActividad::clean()
{
    if(documento)
    {
        delete documento;
        documento=0;
    }
    if(cursor)
    {
        delete cursor;
        cursor=0;
    }
}

void FichaActividad::preparaDocumento()
{
    documento=new QTextDocument(this);
    cursor=new QTextCursor(documento);
    QFont fuenteNormal=QFont("Arial",12);
    QFont fuenteCabecera=QFont("Arial",13);
    fuenteCabecera.setBold(true);

    this->textoNormal=cursor->charFormat();

    textoNormal.setFont(fuenteNormal);
    textoCabecera=textoNormal;
    textoCabecera.setFont(fuenteCabecera);
}

void FichaActividad::generaCabecera(QSqlRecord act)
{
    QTextTable *tablaCabecera;
    QTextTableFormat formatoTabla,formatoCabecera;
    QTextTableCell celdaCabecera;
    QVector<QTextLength> tamColumnas;
    QVector<QTextLength> tamCabecera;

    int posicion;

    tamColumnas << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::PercentageLength,80);

    tamCabecera << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::PercentageLength,10)
            << QTextLength(QTextLength::PercentageLength,90);

    formatoTabla.setColumnWidthConstraints(tamColumnas);
    formatoCabecera.setColumnWidthConstraints(tamCabecera);
    formatoCabecera.setAlignment(Qt::AlignCenter);

    tablaCabecera=cursor->insertTable(4,3,formatoCabecera);

    cursor->insertText("ID "+act.value("IDact").toString(),textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    celdaCabecera=tablaCabecera->cellAt(*cursor);

    tablaCabecera->mergeCells(celdaCabecera.row(),celdaCabecera.column(),1,tablaCabecera->columns());
    cursor->insertText(evento,textoCabecera);
    cursor->movePosition(QTextCursor::NextRow);
    cursor->insertText(act.value("tipoAct").toString(),textoCabecera);
    celdaCabecera=tablaCabecera->cellAt(*cursor);
    tablaCabecera->mergeCells(celdaCabecera.row(),celdaCabecera.column(),tablaCabecera->rows(),1);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Actividad: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("nombre").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextRow);
    cursor->insertText("Asociacion: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("asociacion").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextRow);
    cursor->insertText("Responsable: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("responsable").toString(),textoNormal);


    cursor->movePosition(QTextCursor::End);
    cursor->insertBlock();
    cursor->insertBlock();

}

void FichaActividad::generaHorario(QSqlRecord act)
{
    QTextTable *tablaHorario;
    QTextTable *tablaAnidada;
    QTextTableCell celdaHorario;
    QTextTableFormat formatoTabla;
    QDate fecha;
    QTime horaInicio=act.value("horaInicio").toTime();
    QTime horaFin=act.value("horaFin").toTime();
    QDate fechaActividad=act.value("dia").toDate();
    QVector<QTextLength> tamColumnas;
    int posicion;
    int numDias;
    bool flagHora=false;

    numDias=inicio.daysTo(fin)+1;
    fecha=inicio;

    tamColumnas << QTextLength(QTextLength::PercentageLength,10);

    for(int i=0;i<(numDias*2);i++)
        tamColumnas << QTextLength(QTextLength::PercentageLength,(int)(90/(numDias*2)));

    formatoTabla.setColumnWidthConstraints(tamColumnas);
    formatoTabla.setAlignment(Qt::AlignCenter);

    tablaHorario=cursor->insertTable(5,1+(numDias*2));

    tablaHorario->setFormat(formatoTabla);
    //Fusionar celdas
    celdaHorario=tablaHorario->cellAt(*cursor);

    tablaHorario->mergeCells(celdaHorario.row(),celdaHorario.column(),1,1+(numDias*2));
    cursor->insertText("Horario",textoCabecera);
    cursor->movePosition(QTextCursor::NextRow);

    cursor->movePosition(QTextCursor::NextCell);

    for(int i=0;i<numDias;i++)
    {
        celdaHorario=tablaHorario->cellAt(*cursor);
        tablaHorario->mergeCells(celdaHorario.row(),celdaHorario.column(),1,2);
        cursor->insertText(fecha.toString("dddd"),textoCabecera);
        fecha=fecha.addDays(1);
        cursor->movePosition(QTextCursor::NextCell);
    }
    posicion=cursor->position();
    cursor->insertText("AM",textoCabecera);
    cursor->movePosition(QTextCursor::NextRow);
    cursor->insertText("PM",textoCabecera);

    cursor->setPosition(posicion);

    //Hora de inicio
    if(horaInicio >QTime::fromString("12:00:00","HH:mm:ss"))  //Hora de inicio posterior al mediodia
        cursor->movePosition(QTextCursor::NextRow);

    cursor->movePosition(QTextCursor::NextCell);
    fecha=inicio;
    for(int i=0;i<numDias && !flagHora;i++)
    {
        if(fecha==fechaActividad)   //Estamos en el día correcto
        {
            cursor->insertText(horaInicio.toString("HH:mm"),textoNormal);

            if(horaInicio <= QTime::fromString("12:00","HH:mm") &&      //Los dos antes del mediodia, puedo pasar a la siguiente celda y escribir
               horaFin <= QTime::fromString("12:00","HH:mm"))
            {
                cursor->movePosition(QTextCursor::NextCell);
                cursor->insertText(horaFin.toString("HH:mm"),textoNormal);
                cursor->movePosition(QTextCursor::NextRow);
            }

            if(horaInicio <=QTime::fromString("12:00","HH:mm") &&   //Hora de fin posterior al mediodía, bajar una fila
               horaFin > QTime::fromString("12:00","HH:mm"))
            {
                cursor->movePosition(QTextCursor::NextRow);
                cursor->movePosition(QTextCursor::NextCell);
                cursor->movePosition(QTextCursor::NextCell);
                bool found=false;
                QDate fechaAux=inicio;
                for(int j=0;j<numDias && !found;j++)
                {
                    if(fechaAux!=fechaActividad)
                    {
                        cursor->movePosition(QTextCursor::NextCell);
                        cursor->movePosition(QTextCursor::NextCell);
                        fechaAux=fechaAux.addDays(1);
                    }
                    else found=true;
                }
                cursor->insertText(horaFin.toString("HH:mm"),textoNormal);
            }

            if(horaInicio > QTime::fromString("12:00","HH:mm") &&       //Ambas horas son poasteriores al mediodia
               horaFin > QTime::fromString("12:00","HH:mm"))
            {
                cursor->movePosition(QTextCursor::NextCell);
                cursor->insertText(horaFin.toString("HH:mm"),textoNormal);
            }

            flagHora=true;
        }
        else
        {
            cursor->movePosition(QTextCursor::NextCell,QTextCursor::MoveAnchor,2);
            fecha=fecha.addDays(1);
        }
    }

    cursor->movePosition(QTextCursor::NextRow);

    celdaHorario=tablaHorario->cellAt(*cursor);

    tablaHorario->mergeCells(celdaHorario.row(),celdaHorario.column(),1,3);
    cursor->insertText("Localizacion: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);

    celdaHorario=tablaHorario->cellAt(*cursor);
    tablaHorario->mergeCells(celdaHorario.row(),celdaHorario.column(),1,tablaHorario->columns());
    cursor->insertText(act.value("localizacion").toString(),textoNormal);
    cursor->movePosition(QTextCursor::End);

    cursor->insertBlock();
    cursor->insertBlock();

}

void FichaActividad::mostrarFicha(QSqlRecord act)
{
    DialogReport *ventana=new DialogReport();

    ventana->setDocument(this->documento);
    ventana->setWindowTitle("Ficha de actividad");

    ventana->exec();
    delete ventana;
}


QString FichaActividad::getEvento() const
{
    return this->evento;
}

void FichaActividad::conecta(bool estado)
{
    if(estado)  // conectar generador
    {
        QSqlQuery query(QSqlDatabase::database("evento"));

        query.exec("SELECT nombreEvento,inicio,fin FROM evento");
        query.first();

        evento=query.value(0).toString();
        inicio=QDate::fromString(query.value(1).toString(),QString("yyyy-MM-dd"));
        fin=QDate::fromString(query.value(2).toString(),QString("yyyy-MM-dd"));

    }
    else
    {
        evento.clear();
        inicio.currentDate();
        fin.currentDate();
    }
}

void FichaActividad::generaDescripcion(QSqlRecord act)
{
   QTextTable *tablaDescripcion;
   QTextTableCell celdaDescripcion;
   QTextTableFormat formatoTabla;

   tablaDescripcion=cursor->insertTable(3,3);
   formatoTabla=tablaDescripcion->format();
   formatoTabla.setHeaderRowCount(1);
   formatoTabla.setAlignment(Qt::AlignCenter);
   tablaDescripcion->setFormat(formatoTabla);

   celdaDescripcion=tablaDescripcion->cellAt(*cursor);
   tablaDescripcion->mergeCells(celdaDescripcion.row(),celdaDescripcion.column(),1,2);
   cursor->insertText("Descripcion",textoCabecera);
   cursor->movePosition(QTextCursor::NextCell);
   cursor->insertText("ID "+act.value("IDact").toString(),textoCabecera);

   cursor->movePosition(QTextCursor::NextRow);
   celdaDescripcion=tablaDescripcion->cellAt(*cursor);
   tablaDescripcion->mergeCells(celdaDescripcion.row(),celdaDescripcion.column(),1,tablaDescripcion->columns());

   cursor->insertHtml(act.value("descripcion").toString());
   cursor->movePosition(QTextCursor::NextRow);
   cursor->insertText("Requisitos: ",textoCabecera);
   cursor->movePosition(QTextCursor::NextCell);
   celdaDescripcion=tablaDescripcion->cellAt(*cursor);
   tablaDescripcion->mergeCells(celdaDescripcion.row(),celdaDescripcion.column(),1,tablaDescripcion->columns());

   cursor->insertText(act.value("requisitos").toString(),textoNormal);

   cursor->movePosition(QTextCursor::End);
   cursor->insertBlock();
   cursor->insertBlock();

}

void FichaActividad::generaParticipantes(QSqlRecord act)
{
    QTextTable *tablaParticipantes;

    QTextTableCell celdaParticipantes;
    QTextTableFormat formatoTabla;
    QVector<QTextLength> tamColumnas;

    cursor->movePosition(QTextCursor::End);
    formatoTabla.setHeaderRowCount(1);
    formatoTabla.setColumnWidthConstraints(tamColumnas);

    tamColumnas << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::VariableLength,0)
            << QTextLength(QTextLength::VariableLength,0);

    tablaParticipantes=cursor->insertTable(2,6,formatoTabla);


    cursor->insertText("ID "+act.value("IDact").toString(),textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Lista de participantes",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Minimo: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("minPart").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Maximo: ",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("maxPart").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextRow);


    celdaParticipantes=tablaParticipantes->cellAt(*cursor);

    tablaParticipantes->mergeCells(celdaParticipantes.row(),celdaParticipantes.column(),1,tablaParticipantes->columns());

    cursor->insertText(QString(" ").repeated(500));
    for(int i=0;i<25;i++)
        cursor->insertBlock();

}

void FichaActividad::generaFichasSeleccionadas(QSqlQuery listaActividades,QString directorio)
{    
    QSqlQueryModel modelo(this);
    modelo.setQuery(listaActividades);

    QProgressDialog barraProgreso("Generando fichas de actividades...","Cancelar",0,modelo.rowCount());

    barraProgreso.setMinimumDuration(0);
    for(int i=0;i<modelo.rowCount();i++)
    {
        barraProgreso.setValue(i);
        clean();
        preparaDocumento();
        generaCabecera(modelo.record(i));
        generaHorario(modelo.record(i));
        generaDescripcion(modelo.record(i));
        generaParticipantes(modelo.record(i));
        this->saveFicha(directorio+"/actividad"+modelo.record(i).value("IDact").toString()+".pdf",PDF);
    }
    barraProgreso.setValue(modelo.rowCount());
}

void FichaActividad::generaImprimeFichasDia(QSqlQuery listaDia)
{
    QSqlQueryModel modelo(this);
    modelo.setQuery(listaDia);
    QPrinter *impresora=new QPrinter();

    QPrintDialog *dialogo=new QPrintDialog(impresora,qobject_cast<QWidget*>(this->parent()));
    if(dialogo->exec()==QDialog::Accepted)  // Impresora configurada
    {
        for(int i=0;i<modelo.rowCount();i++)
        {
            clean();
            preparaDocumento();
            generaCabecera(modelo.record(i));
            generaHorario(modelo.record(i));
            generaDescripcion(modelo.record(i));
            generaParticipantes(modelo.record(i));
            imprime(impresora);
        }
    }
    delete dialogo;
    delete impresora;
}


void FichaActividad::saveFicha(QString nombreArchivo, FormatoSalida formato)
{
    if(formato==PDF)
    {
        QPrinter printer;
        printer.setOutputFileName(nombreArchivo);
        printer.setOutputFormat(QPrinter::PdfFormat);

        this->documento->print(&printer);
    }
    if(formato==ODT)
    {
        QTextDocumentWriter writer;

        QFile archivo(nombreArchivo);

        archivo.open(QFile::WriteOnly);

        writer.setDevice(&archivo);

        writer.write(documento);
        archivo.close();
    }
}


void FichaActividad::generaFichaSala(QSqlQuery listaActividades, QString sala, QString directorio)
{
    QSqlQueryModel modelo;
    int numFilas;
    clean();
    preparaDocumento();
    modelo.setQuery(listaActividades);
    numFilas=modelo.rowCount();

    QProgressDialog barraProgreso("Generando informe de actividad en sala "+sala,"Cancelar",0,numFilas);
    barraProgreso.setMinimumDuration(0);
    generaNombreSala(sala);
    for(int i=0;i<numFilas;i++)
    {
        generaActividadEnSala(modelo.record(i));
        barraProgreso.setValue(i);
    }

    saveFicha(directorio.append("/")+sala.prepend("informe").replace(' ','_').append(".pdf"),PDF);
    barraProgreso.setValue(numFilas);

}

void FichaActividad::generaImprimeFichaSala(QSqlQuery listaActividades, QString sala,QPrinter *impresora)
{
    QSqlQueryModel modelo;
    int numFilas;
    clean();
    preparaDocumento();
    modelo.setQuery(listaActividades);
    numFilas=modelo.rowCount();

        generaNombreSala(sala);
        for(int i=0;i<numFilas;i++)
        {
            generaActividadEnSala(modelo.record(i));
        }
        this->imprime(impresora);
}

void FichaActividad::generaNombreSala(QString nombre)
{
    QTextCharFormat formatoCabecera=textoCabecera;
    QTextTableFormat formatoTabla;

    formatoCabecera.setFontPointSize(30);
    formatoCabecera.setFontUnderline(true);
    formatoCabecera.setFontItalic(true);

    cursor->insertText(nombre,formatoCabecera);

    cursor->insertBlock();
    cursor->insertTable(1,6);
    formatoTabla=cursor->currentTable()->format();
    formatoTabla.setHeaderRowCount(1);
    cursor->currentTable()->setFormat(formatoTabla);
    cursor->insertText("Actividad",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Categoria",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Dia",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Hora de inicio",textoCabecera);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Hora de fin",textoCabecera);

    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText("Estado",textoCabecera);
}

void FichaActividad::generaActividadEnSala(QSqlRecord act)
{
    cursor->currentTable()->appendRows(1);
    cursor->movePosition(QTextCursor::PreviousRow);
    cursor->movePosition(QTextCursor::NextRow);
    cursor->insertText(act.value("nombre").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("tipoAct").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("dia").toDate().toString("dddd, 'd'ia dd"),textoNormal);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("horaInicio").toString(),textoNormal);
    cursor->movePosition(QTextCursor::NextCell);
    cursor->insertText(act.value("horaFin").toString(),textoNormal);

    cursor->movePosition(QTextCursor::NextCell);
    switch(act.value("estado").toInt())
    {
    case 0:
        cursor->insertImage(okImage);
        break;
    case 1:
        cursor->insertImage(delayImage);
        break;
    case 2:
        cursor->insertImage(cancelImage);
        break;
    default:
        break;
    }

}

void FichaActividad::imprimeFicha()
{
    QPrintDialog *dialog=new QPrintDialog(qobject_cast<QWidget*>(this->parent()));

    connect(dialog,SIGNAL(accepted(QPrinter*)),this,SLOT(imprime(QPrinter*)));

    dialog->exec();
    delete dialog;
}

void FichaActividad::imprime(QPrinter *impresora)
{
    this->documento->print(impresora);
}
